const { Op } = require('sequelize');
const Field = require('../models/Field');
const _Certificate = require('../models/Certificate');
const logger = require('../utils/logger');
const sequelize = require('../config/database');
const redis = require('../config/redis');

// 缓存键前缀
const CACHE_KEY = {
  FIELD_LIST: 'field:list:',
  FIELD_DETAIL: 'field:detail:',
  AVAILABLE_FIELDS: 'field:available:'
};

// 缓存时间(秒)
const CACHE_TTL = {
  FIELD_LIST: 60 * 60, // 1小时
  FIELD_DETAIL: 60 * 60 * 24 // 24小时
};

// 获取字段列表
exports.getFields = async (req, res) => {
  try {
    const { page = 1, limit = 10, name } = req.query;
    const offset = (page - 1) * limit;
    
    // 生成缓存键
    const cacheKey = `${CACHE_KEY.FIELD_LIST}${page}:${limit}:${name || ''}`;
    
    // 尝试从缓存获取
    const cachedData = await redis.get(cacheKey);
    if (cachedData) {
      logger.info('从缓存获取字段列表');
      return res.json(JSON.parse(cachedData));
    }
    
    const where = {};
    if (name) {
      where.name = {
        [Op.like]: `%${name}%`
      };
    }
    
    // 确保证书编号字段存在
    const certNumberField = await Field.findByPk(1);
    if (!certNumberField) {
      await Field.create({
        id: 1,
        name: '证书编号',
        description: '证书的唯一编号'
      });
    }
    
    const { count, rows } = await Field.findAndCountAll({
      where,
      offset,
      limit: parseInt(limit),
      order: [
        ['createdAt', 'ASC']
      ]
    });
    
    const result = {
      code: 200,
      data: {
        total: count,
        items: rows
      }
    };

    // 设置缓存
    await redis.set(cacheKey, JSON.stringify(result), 'EX', CACHE_TTL.FIELD_LIST);
    logger.info('字段列表已缓存');
    
    res.json(result);
  } catch (error) {
    logger.error('Get fields error:', error);
    res.status(500).json({
      code: 500,
      message: '获取字段列表失败'
    });
  }
};

// 创建字段
exports.createField = async (req, res) => {
  try {
    const { name, description } = req.body;

    if (name === '证书编号') {
      return res.status(400).json({
        code: 400,
        message: '证书编号字段已存在，不能重复创建'
      });
    }

    const timestamp = Date.now();
    const field_name = `${name.toLowerCase().replace(/\s+/g, '_')}_${timestamp}`;

    const maxField = await Field.findOne({
      order: [['id', 'DESC']]
    });
    
    const newId = Math.max((maxField?.id || 1) + 1, 2);

    const field = await Field.create({
      id: newId,
      name,
      field_name,
      description
    });

    // 清除字段列表相关的所有缓存
    const keys = await redis.keys(`${CACHE_KEY.FIELD_LIST}*`);
    if (keys.length > 0) {
      await redis.del(keys);
      logger.info('字段列表缓存已清除');
    }

    res.json({
      code: 200,
      data: field,
      message: '创建字段成功'
    });
  } catch (error) {
    logger.error('Create field error:', error);
    res.status(500).json({
      code: 500,
      message: '创建字段失败',
      error: process.env.NODE_ENV === 'development' ? error.message : undefined
    });
  }
};

// 添加一个工具函数来判断是否是系统字段
const isSystemField = (field) => {
  return field.id <= 8; // ID 1-8为系统字段
};

// 更新字段
exports.updateField = async (req, res) => {
  try {
    const { id } = req.params;
    const { name, description } = req.body;

    // 查找字段
    const field = await Field.findByPk(id);
    if (!field) {
      return res.status(404).json({
        code: 404,
        message: '字段不存在'
      });
    }

    // 检查是否是系统字段
    if (isSystemField(field)) {
      return res.status(403).json({
        code: 403,
        message: '系统字段不允许修改'
      });
    }

    // 更新字段（不修改 field_name，保持原值）
    await field.update({
      name,
      description
    });

    // 清除字段相关的所有缓存
    const fieldKeys = await redis.keys(`${CACHE_KEY.FIELD_LIST}*`);
    const availableKeys = await redis.keys(`${CACHE_KEY.AVAILABLE_FIELDS}*`);
    const keys = [...fieldKeys, ...availableKeys];
    if (keys.length > 0) {
      await redis.del(keys);
      logger.info('字段相关缓存已清除');
    }

    res.json({
      code: 200,
      data: field,
      message: '更新字段成功'
    });
  } catch (error) {
    logger.error('Update field error:', error);
    res.status(500).json({
      code: 500,
      message: '更新字段失败',
      error: process.env.NODE_ENV === 'development' ? error.message : undefined
    });
  }
};

// 删除字段
exports.deleteField = async (req, res) => {
  try {
    const { id } = req.params;
    logger.info('开始删除字段，ID:', id);

    // 查找字段
    const field = await Field.findByPk(id);
    if (!field) {
      logger.warn('字段不存在:', id);
      return res.status(404).json({
        code: 404,
        message: '字段不存在'
      });
    }
    logger.info('找到字段:', field.toJSON());

    // 检查是否是系统字段
    if (isSystemField(field)) {
      logger.warn('尝试删除系统字段:', field.toJSON());
      return res.status(403).json({
        code: 403,
        message: '系统字段不允许删除'
      });
    }

    // 检查字段名称是否存在
    if (!field.field_name) {
      logger.warn('字段标识为空:', field.toJSON());
      return res.status(400).json({
        code: 400,
        message: '字段标识不能为空'
      });
    }

    // 检查是否有证书正在使用该字段
    const [results] = await sequelize.query(
      `SELECT COUNT(*) as count, GROUP_CONCAT(sequence_number) as cert_numbers 
       FROM certificates 
       WHERE JSON_CONTAINS(fields, JSON_OBJECT('field_name', '${field.field_name}'), '$[*]')`
    );

    const { count, cert_numbers } = results[0];
    logger.info('字段使用检查结果:', { count, cert_numbers });
    
    if (count > 0) {
      logger.warn(`字段 ${id} 被以下证书使用: ${cert_numbers}`);
      return res.status(403).json({
        code: 403,
        message: `该字段已被${count}个证书使用（证书编号：${cert_numbers}），不能删除`
      });
    }

    // 删除字段
    await field.destroy();
    logger.info('字段删除成功:', id);

    // 清除字段相关的所有缓存
    const fieldKeys = await redis.keys(`${CACHE_KEY.FIELD_LIST}*`);
    const availableKeys = await redis.keys(`${CACHE_KEY.AVAILABLE_FIELDS}*`);
    const keys = [...fieldKeys, ...availableKeys];
    if (keys.length > 0) {
      await redis.del(keys);
      logger.info('字段相关缓存已清除');
    }

    res.json({
      code: 200,
      message: '删除字段成功'
    });
  } catch (error) {
    logger.error('删除字段失败:', error);
    // 处理特定的错误类型
    if (error.message && error.message.includes('证书使用')) {
      return res.status(403).json({
        code: 403,
        message: error.message
      });
    }
    // 其他错误返回 500
    res.status(500).json({
      code: 500,
      message: '删除字段失败',
      error: process.env.NODE_ENV === 'development' ? error.message : undefined
    });
  }
}; 